/*
* @Date: 2021/2/23
* @Author: XueChengwu <xuechengwu@erayt.com>
* @Copyright: 2015-2019 Erayt, Inc.
* @Description: If you have some questions, please contact: xuechengwu@erayt.com.
*/
import controller from '../core/controller'
import { get, post } from '../core/route';
import { db, tran, id } from '../core/db/mysql/db';
import Query from '../core/db/mysql/query';
import { login } from '../decorater/auth'
import utils from '../core/utils';
import config from '../core/config';
import fs from 'fs';
import path from 'path';

@controller()
export default class posts {
  /**
   * 最新
   * @returns {Promise<void>}
   */
  @get('/api/post/list')
  async list() {
    const { topic = '' } = this.params;
    const where = this.params;
    const userid = this.session.userid;
    try {
      await db(async conn => {
        let postQuery = new Query(conn, 'bu_post');
        if (topic !== '') {
          postQuery.where('topic', topic);
        }
        postQuery.alias('p')
          .fields('p.*, u.username, u.avatar')
          .join('bu_user as u', 'u.id = p.user', 'left');
        const posts = await postQuery.order('addtime desc').page(
          where.page ? where.page : 1, 15, where);
        if (userid) {
          const postIds = posts.data.map(vo => vo.id);
          const voteQuery = new Query(conn, 'bu_post_vote');
          const votes = await voteQuery.where('post', 'in', postIds.join(',')).where('user', userid).select();
          for (let i = 0; i < votes.length; i++) {
            const postIndex = posts.data.findIndex(vo => vo.id === votes[i].post);
            if (postIndex >= 0) {
              posts.data[postIndex].vote = votes[i].vote;
            }
          }
        }
        this.assign('posts', posts);
      });
      return this.setCode(0).setMsg('success').json();
    } catch(err) {
      console.log('err===>', err);
      return this.setCode(1).setMsg('请求失败').json();
    }
  }

  @get('/api/post/hots')
  async hots() {
    const { topic = '' } = this.params;
    const where = this.params;
    const userid = this.session.userid;
    try {
      await db(async conn => {
        let postQuery = new Query(conn, 'bu_post');
        if (topic !== '') {
          postQuery.where('topic', topic);
        }
        postQuery.alias('p')
          .fields('p.*, u.username, u.avatar')
          .join('bu_user as u', 'u.id = p.user', 'left');
        postQuery.where(
          'p.addtime',
          '>=',
          utils.formatDate(new Date(new Date().getTime() - 5 * 24 * 60 * 60 * 1000), 'yyyy-MM-dd hh:mm:ss')
        );
        const posts = await postQuery.order('p.hot desc, p.addtime desc').page(
          where.page ? where.page : 1, 15, where);
        if (userid) {
          const postIds = posts.data.map(vo => vo.id);
          const voteQuery = new Query(conn, 'bu_post_vote');
          if (postIds.length > 0) {
            voteQuery.where('post', 'in', postIds.join(','));
          }
          const votes = await voteQuery.where('user', userid).select();
          for (let i = 0; i < votes.length; i++) {
            const postIndex = posts.data.findIndex(vo => vo.id === votes[i].post);
            if (postIndex >= 0) {
              posts.data[postIndex].vote = votes[i].vote;
            }
          }
        }
        this.assign('posts', posts);
      });
      return this.setCode(0).setMsg('success').json();
    } catch(err) {
      console.log('err===>', err);
      return this.setCode(1).setMsg('请求失败').json();
    }
  }

  /**
   * 关注
   * @returns {Promise<void>}
   */
  @login
  @get('/api/post/stars')
  async stars() {
    const { topic = '' } = this.params;
    const where = this.params;
    const userid = this.session.userid;
    try {
      await db(async conn => {
        const starQuery = new Query(conn, 'bu_user_star');
        const stars = await starQuery.where('user', userid).select();
        const userIds = stars.map(vo => vo.starUser);
        let postQuery = new Query(conn, 'bu_post');
        if (topic !== '') {
          postQuery.where('topic', topic);
        }
        postQuery.alias('p')
          .fields('p.*, u.username, u.avatar')
          .where('p.user', 'in', userIds.join(','))
          .join('bu_user as u', 'u.id = p.user', 'left');
        const posts = await postQuery.order('addtime desc').page(
          where.page ? where.page : 1, 15, where);
        if (userid) {
          const postIds = posts.data.map(vo => vo.id);
          const voteQuery = new Query(conn, 'bu_post_vote');
          const votes = await voteQuery.where('post', 'in', postIds.join(',')).where('user', userid).select();
          for (let i = 0; i < votes.length; i++) {
            const postIndex = posts.data.findIndex(vo => vo.id === votes[i].post);
            if (postIndex >= 0) {
              posts.data[postIndex].vote = votes[i].vote;
            }
          }
        }
        this.assign('posts', posts);
      });
      return this.setCode(0).setMsg('请求成功').json();
    } catch (err) {
      return this.setCode(1).setMsg('请求失败').json();
    }
  }

  @login
  @post('/api/post/add')
  async add() {
    const { content = '' } = this.params;
    const { userid } = this.session;
    let files = this.ctx.request.files.files;
    if (!(files instanceof Array)) {
      files = [files];
    }
    const paths = [];
    try {
      for (let file of files) {
        const reader = fs.createReadStream(file.path);
        const dir = config.upload.path + '/' + utils.formatDate(new Date(), 'yyyyMMdd');
        const filePath = dir + `/${utils.getGuid()}.${file.name.substr(file.name.lastIndexOf('.') + 1)}`;
        const isExists = fs.existsSync(path.join(__dirname, `../static/${dir}`));
        if(!isExists) {
          fs.mkdirSync(path.join(__dirname, `../static/${dir}`));
        }
        const absolutePath = path.join(__dirname, `../static/${filePath}`);
        const upStream = fs.createWriteStream(absolutePath);
        reader.pipe(upStream);
        paths.push(filePath);
      }
      const postModal = {
        user: userid,
        addtime: utils.formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss'),
        content,
        medias: paths.join(';'),
      };
      await db(async conn => {
        const postQuery = new Query(conn, 'bu_post');
        await postQuery.insert(postModal);
      });
      return this.setCode(0).setMsg('发布成功').json();
    } catch(err) {
      console.log('error ====>', err);
      for (let i = 0; i < paths.length; i++) {
        const filePath = path.join(__dirname, `../static/${paths[i]}`);
        const isExists = fs.existsSync(filePath);
        if (isExists) {
          fs.unlinkSync(filePath);
        }
      }
      return this.setCode(1).setMsg('发布失败').json();
    }
  }

  @get('/api/post/detail')
  async detail() {
      const { id } = this.params;
      try {
        await db(async conn => {
          const postQuery = new Query(conn, 'bu_post');
          const post = await postQuery.alias('p')
            .join('bu_user as u', 'p.user = u.id', 'LEFT')
            .where('p.id', id)
            .fields('p.*, u.avatar, u.username')
            .find();
          const userid = this.session.userid;
          if (userid) {
            const postVoteQuery = new Query(conn, 'bu_post_vote');
            const votes = await postVoteQuery.where('post', post.id)
              .where('user', userid)
              .find();
            if(votes) {
              post.vote = votes.vote;
            }
          }
          this.assign('post', post);
        });
        return this.setCode(0).setMsg('获取成功').json();
      } catch(err) {
        console.log('error===>', err);
        return this.setCode(1).setMsg('获取失败').json();
      }
  }

  @get('/api/post/comments')
  async comments() {
    const { id } = this.params;
    try {
      await db(async conn => {
        const commentQuery = new Query(conn, 'bu_comment');
        const comments = await commentQuery.alias('c')
          .where('c.post', id)
          .join('bu_user as u1', 'c.user = u1.id', 'LEFT')
          .join('bu_user as u2', 'c.tocomment = u2.id', 'LEFT')
          .fields('c.*, u1.avatar, u1.username as author, u2.username as author2')
          .select();
        this.assign('comments', comments);
      });
      return this.setCode(0).setMsg('获取成功').json();
    } catch(err) {
      console.log('error===>', err);
      return this.setCode(1).setMsg('获取失败').json();
    }
  }

  @login
  @post('/api/post/comment')
  async comment() {
    const comment = this.params;
    const { userid } = this.session;
    try {
      await tran(async conn => {
        const commentQuery = new Query(conn, 'bu_comment');
        const postQuery = new Query(conn, 'bu_post');
        const commentModal = {
          user: userid,
          post: comment.post,
          content: comment.content,
          addtime: utils.formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss'),
          tocomment: comment.to || 0,
        };
        await commentQuery.insert(commentModal);
        const postModal = await postQuery.where('id', comment.post).find();
        const targetModal = {
          commentNum: Number(postModal.commentNum) + 1,
          hot: Number(postModal.hot) + 1,
        };
        await postQuery.where('id', comment.post).update(targetModal);
      });
      return this.setCode(0).setMsg('评论成功').json();
    } catch(err) {
      console.log('error====>', err);
      return this.setCode(1).setMsg('评论失败').json();
    }
  }

  @login
  @post('/api/post/vote')
  async vote() {
    const { post, vote, status } = this.params;
    const { userid } = this.session;
    try {
      await tran(async conn => {
        const postVoteQuery = new Query(conn, 'bu_post_vote');
        const postQuery = new Query(conn, 'bu_post');
        if (Number(status) === 1) {
          // 取消
          const postModal = await postQuery.where('id', post).find();
          await postVoteQuery.where('post', post).where('user', userid).where('vote', vote).delete();
          if (vote === 1) {
            postModal.upvote = postModal.upvote - 1;
          } else {
            postModal.downvote = postModal.downvote - 1;
          }
          postModal.hot = postModal.hot - 1;
          delete postModal.addtime;
          await postQuery.where('id', post).update(postModal);
          this.assign('post', postModal);
        } else {
          // 点赞或踩
          const postModal = await postQuery.where('id', post).find();
          if (vote === 1) {
            postModal.upvote = postModal.upvote + 1;
          } else {
            postModal.downvote = postModal.downvote + 1;
          }
          postModal.hot = postModal.hot + 1;
          const postVote = await postVoteQuery
            .where('post', post)
            .where('user', userid)
            .where('vote', vote)
            .find();
          if (!postVote) {
            await postVoteQuery.insert({
              post,
              vote,
              user: userid,
              addtime: utils.formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss'),
            });
          }
          delete postModal.addtime;
          await postQuery.where('id', post).update(postModal);
          this.assign('post', postModal);
        }
      });
      return this.setCode(0).setMsg('操作成功').json();
    } catch (err) {
      console.log('error===>', err);
      return this.setCode(1).setMsg('操作失败').json();
    }
  }

  @post('/api/post/mine')
  async mine() {

  }
}
